package cn.ges.ali.sms;

import cn.ges.random.RandomUtil;
import cn.ges.redis.RedisUtil;
import cn.ges.string.StringUtil;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.profile.DefaultProfile;
import lombok.NonNull;
import org.springframework.stereotype.Component;

import java.util.HashMap;

/**
 * 短信工具类
 *
 * @author gespent@163.com
 * @date 2018/12/19
 */
@Component
public class SmsUtil {


    /**
     * 一个用户60S只能发送一次短信限制 前缀
     */
    private static final String REDIS_SMS_TEMP_CACHE_PREFIX = "SMS_T_";

    public static void init(@NonNull String accessKeyId, @NonNull String accessKeySecret) {
        AliyunSms.profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
    }

    /**
     * 检查验证码是否正确,仅在使用了RedisUtil时有效
     *
     * @param phoneNumber 收取验证码的手机号
     * @param code        验证码
     * @return true/false
     */
    public static boolean checkCodeCorrect(String phoneNumber, String code, String container) {
        final String key = container + phoneNumber;
        String result = (String) RedisUtil.get(key);
        if (result == null) {
            return false;
        }
        if (result.equals(code)) {
            // 删除该验证码
            RedisUtil.del(key);
            return true;
        } else {
            // 验证码错误
            return false;
        }
    }


    /**
     * 工具 -> 检查手机是否是11位，检查该用户是否重复发送
     */
    private static Integer checkState(String phoneNumber) {
        if (StringUtil.isBlank(phoneNumber) || phoneNumber.length() != 11) {
            return 0;
        }
        // 查找缓存 是否60S内重复发送
        if (RedisUtil.hasKey(REDIS_SMS_TEMP_CACHE_PREFIX + phoneNumber)) {
            // 命中缓存直接返回超过限制
            return 2;
        }
        return null;
    }

    /**
     * 发送一条注册验证码 同一个手机号码60S只能发送一条短信,必须要在RedisUtil启用后才能调用
     *
     * @param phoneNumber 收取验证码的手机号
     * @param smsTemplate 发送短信模版类型 如 Constant.SMS_TEMPALTE_REGISTER 是注册类短信
     * @param container   指定验证码容器(redis) 如 REDIS_REGISTER_CACHE_PREFIX 是注册类短信容器
     * @return 0:错误或者为空的手机号码
     * 1:发送失败
     * 2:超过发送限制
     * 3：发送成功
     */
    public static Integer sendMessage(String phoneNumber, String smsTemplate, String container, String signName) {
        Integer integer = checkState(phoneNumber);
        if (integer != null) {
            return integer;
        }
        HashMap<String, String> map = new HashMap<>(1);
        String checkCode = getCheckCode();
        map.put("code", checkCode);
        SendSmsResponse sendSmsResponse = AliyunSms.sendSms(signName, smsTemplate, map, phoneNumber);
        String successMessage = "OK";
        if (sendSmsResponse.getCode() != null && successMessage.equals(sendSmsResponse.getCode())) {
            //请求成功
            // 设置短信十分钟内有效
            RedisUtil.set(container + phoneNumber, checkCode, 600);
            // 设置该用户60S内不能继续发送
            RedisUtil.set(REDIS_SMS_TEMP_CACHE_PREFIX + phoneNumber, true, 60);
            return 3;
        } else {
            return 1;
        }
    }

    /**
     * 生成六位数字验证码
     *
     * @return 生成的验证码
     */
    public static String getCheckCode() {
        return Long.toString(RandomUtil.get6RandomNumber());
    }
}
